import { prisma } from '@/lib/database'
import { cache } from '@/lib/redis'
import { FileService } from '@/services/fileService'
import { config } from '@/config/env'
import {
  ValidationError,
  ConflictError,
  NotFoundError
} from '@/middleware/errorHandler'

// 类型定义
export interface CreatePluginData {
  name: string
  displayName: string
  description?: string
  category: string
  repositoryUrl?: string
  homepageUrl?: string
  documentationUrl?: string
  license?: string
  keywords?: string[]
  tags?: string[]
}

export interface UploadVersionData {
  version: string
  changelog?: string
  fileBuffer: Buffer
  originalFileName: string
  mimetype: string
}

export interface PluginSearchQuery {
  search?: string
  category?: string
  tags?: string[]
  featured?: boolean
  verified?: boolean
  sort?: 'downloads' | 'rating' | 'updated' | 'created'
  order?: 'asc' | 'desc'
  page?: number
  limit?: number
}

export interface PluginListItem {
  id: string
  name: string
  displayName: string
  description?: string
  category: string
  developer: {
    username: string
    displayName?: string
    verified: boolean
  }
  latestVersion?: string
  totalDownloads: number
  rating: {
    average: number
    count: number
  }
  featured: boolean
  verified: boolean
  tags: string[]
  updatedAt: Date
}

export interface PluginDetails extends PluginListItem {
  repositoryUrl?: string
  homepageUrl?: string
  documentationUrl?: string
  license?: string
  keywords: string[]
  versions: {
    version: string
    publishedAt: Date
    downloadCount: number
    changelog?: string
  }[]
  stats: {
    weeklyDownloads: number
    monthlyDownloads: number
  }
  createdAt: Date
}

export class PluginService {
  private fileService: FileService

  constructor() {
    this.fileService = new FileService()
  }

  // 创建新插件
  async createPlugin(developerId: string, data: CreatePluginData): Promise<any> {
    // 验证插件名称是否已存在
    const existingPlugin = await prisma.plugin.findUnique({
      where: { name: data.name }
    })

    if (existingPlugin) {
      throw new ConflictError('Plugin name already exists')
    }

    // 验证分类是否存在
    const category = await prisma.category.findUnique({
      where: { name: data.category }
    })

    if (!category) {
      throw new ValidationError('Invalid category')
    }

    // 创建插件
    const plugin = await prisma.plugin.create({
      data: {
        name: data.name,
        displayName: data.displayName,
        description: data.description,
        category: data.category,
        developerId,
        repositoryUrl: data.repositoryUrl,
        homepageUrl: data.homepageUrl,
        documentationUrl: data.documentationUrl,
        license: data.license,
        keywords: data.keywords || [],
        tags: data.tags || [],
        status: config.dev.autoApprovePlugins ? 'approved' : 'pending'
      },
      include: {
        developer: {
          select: {
            username: true,
            displayName: true,
            verified: true
          }
        }
      }
    })

    // 清除相关缓存
    await this.clearPluginListCache()

    // 转换BigInt字段
    const result = {
      ...plugin,
      totalDownloads: Number(plugin.totalDownloads),
      ratingAverage: Number(plugin.ratingAverage),
      ratingCount: plugin.ratingCount
    }

    return result
  }

  // 上传插件版本
  async uploadVersion(
    pluginId: string, 
    developerId: string, 
    data: UploadVersionData
  ): Promise<any> {
    // 验证插件所有权
    const plugin = await prisma.plugin.findFirst({
      where: {
        id: pluginId,
        developerId
      }
    })

    if (!plugin) {
      throw new NotFoundError('Plugin not found or access denied')
    }

    // 检查版本是否已存在
    const existingVersion = await prisma.pluginVersion.findUnique({
      where: {
        pluginId_version: {
          pluginId,
          version: data.version
        }
      }
    })

    if (existingVersion) {
      throw new ConflictError('Version already exists')
    }

    // 保存文件
    const uploadedFile = await this.fileService.saveUploadedFile(
      data.fileBuffer,
      data.originalFileName,
      data.mimetype
    )

    try {
      // 解析插件包
      const packageInfo = await this.fileService.parsePluginPackage(uploadedFile.path)

      // 验证插件名称匹配
      if (packageInfo.manifest.name !== plugin.name) {
        throw new ValidationError('Plugin name in manifest does not match registered plugin name')
      }

      // 验证版本匹配
      if (packageInfo.manifest.version !== data.version) {
        throw new ValidationError('Version in manifest does not match specified version')
      }

      // 创建版本记录
      const version = await prisma.pluginVersion.create({
        data: {
          pluginId,
          version: data.version,
          changelog: data.changelog,
          filePath: uploadedFile.path,
          fileSize: uploadedFile.size,
          fileHash: uploadedFile.hash,
          manifest: packageInfo.manifest as any,
          engines: packageInfo.manifest.engines as any,
          permissions: packageInfo.manifest.permissions || [],
          dependencies: packageInfo.manifest.dependencies || {},
          status: config.dev.autoApprovePlugins ? 'approved' : 'pending',
          securityScanStatus: 'pending',
          publishedAt: config.dev.autoApprovePlugins ? new Date() : null
        }
      })

      // 更新插件的最新版本信息
      await prisma.plugin.update({
        where: { id: pluginId },
        data: {
          lastVersion: data.version,
          lastUpdatedAt: new Date()
        }
      })

      // 清除相关缓存
      await this.clearPluginCache(plugin.name)
      await this.clearPluginListCache()

      // 转换BigInt字段以避免JSON序列化问题
      const result = {
        ...version,
        fileSize: Number(version.fileSize),
        downloadCount: Number(version.downloadCount)
      }

      return result

    } catch (error) {
      // 如果处理失败，删除已上传的文件
      await this.fileService.deleteFile(uploadedFile.path)
      throw error
    }
  }

  // 获取插件列表
  async getPluginList(query: PluginSearchQuery): Promise<{
    plugins: PluginListItem[]
    pagination: {
      page: number
      limit: number
      total: number
      totalPages: number
    }
  }> {
    const page = query.page || 1
    const limit = Math.min(query.limit || 20, 100)
    const offset = (page - 1) * limit

    // 构建查询条件
    const where: any = {
      status: 'approved'
    }

    if (query.search) {
      where.OR = [
        { displayName: { contains: query.search, mode: 'insensitive' } },
        { description: { contains: query.search, mode: 'insensitive' } },
        { keywords: { has: query.search } }
      ]
    }

    if (query.category) {
      where.category = query.category
    }

    if (query.featured !== undefined) {
      where.featured = query.featured
    }

    if (query.verified !== undefined) {
      where.verified = query.verified
    }

    if (query.tags && query.tags.length > 0) {
      where.tags = { hasEvery: query.tags }
    }

    // 构建排序条件
    const orderBy: any = []
    const sortField = query.sort || 'created'  // 改为默认按创建时间排序
    const sortOrder = query.order || 'desc'

    switch (sortField) {
      case 'downloads':
        orderBy.push({ totalDownloads: sortOrder })
        break
      case 'rating':
        orderBy.push({ ratingAverage: sortOrder })
        break
      case 'updated':
        // 先按lastUpdatedAt排序，再按createdAt排序
        orderBy.push({ lastUpdatedAt: sortOrder })
        orderBy.push({ createdAt: sortOrder })
        break
      case 'created':
      default:
        orderBy.push({ createdAt: sortOrder })
        break
    }

    // 查询插件
    const [plugins, total] = await Promise.all([
      prisma.plugin.findMany({
        where,
        include: {
          developer: {
            select: {
              username: true,
              displayName: true,
              verified: true
            }
          }
        },
        orderBy,
        skip: offset,
        take: limit
      }),
      prisma.plugin.count({ where })
    ])

    // 转换数据格式
    const pluginList: PluginListItem[] = plugins.map(plugin => ({
      id: plugin.id,
      name: plugin.name,
      displayName: plugin.displayName,
      description: plugin.description || undefined,
      category: plugin.category,
      developer: {
        username: plugin.developer.username,
        displayName: plugin.developer.displayName || undefined,
        verified: plugin.developer.verified
      },
      latestVersion: plugin.lastVersion || undefined,
      totalDownloads: Number(plugin.totalDownloads),
      rating: {
        average: Number(plugin.ratingAverage),
        count: plugin.ratingCount
      },
      featured: plugin.featured,
      verified: plugin.verified,
      tags: plugin.tags,
      updatedAt: plugin.lastUpdatedAt || plugin.createdAt
    }))

    return {
      plugins: pluginList,
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit)
      }
    }
  }

  // 获取插件详情
  async getPluginDetails(pluginName: string): Promise<PluginDetails> {
    // 尝试从缓存获取
    const cacheKey = `plugin:${pluginName}`
    const cached = await cache.get<PluginDetails>(cacheKey)
    if (cached) {
      return cached
    }

    const plugin = await prisma.plugin.findFirst({
      where: {
        name: pluginName,
        status: 'approved'
      },
      include: {
        developer: {
          select: {
            username: true,
            displayName: true,
            verified: true
          }
        },
        versions: {
          where: { status: 'approved' },
          select: {
            version: true,
            publishedAt: true,
            downloadCount: true,
            changelog: true
          },
          orderBy: { publishedAt: 'desc' }
        }
      }
    })

    if (!plugin) {
      throw new NotFoundError('Plugin not found')
    }

    // 计算统计数据
    const now = new Date()
    const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
    const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000)

    const [weeklyDownloads, monthlyDownloads] = await Promise.all([
      prisma.download.count({
        where: {
          pluginId: plugin.id,
          downloadedAt: { gte: weekAgo }
        }
      }),
      prisma.download.count({
        where: {
          pluginId: plugin.id,
          downloadedAt: { gte: monthAgo }
        }
      })
    ])

    const details: PluginDetails = {
      id: plugin.id,
      name: plugin.name,
      displayName: plugin.displayName,
      description: plugin.description || undefined,
      category: plugin.category,
      developer: {
        username: plugin.developer.username,
        displayName: plugin.developer.displayName || undefined,
        verified: plugin.developer.verified
      },
      repositoryUrl: plugin.repositoryUrl || undefined,
      homepageUrl: plugin.homepageUrl || undefined,
      documentationUrl: plugin.documentationUrl || undefined,
      license: plugin.license || undefined,
      keywords: plugin.keywords,
      latestVersion: plugin.lastVersion || undefined,
      totalDownloads: Number(plugin.totalDownloads),
      rating: {
        average: Number(plugin.ratingAverage),
        count: plugin.ratingCount
      },
      featured: plugin.featured,
      verified: plugin.verified,
      tags: plugin.tags,
      versions: plugin.versions.map(v => ({
        version: v.version,
        publishedAt: v.publishedAt!,
        downloadCount: Number(v.downloadCount),
        changelog: v.changelog || undefined
      })),
      stats: {
        weeklyDownloads,
        monthlyDownloads
      },
      createdAt: plugin.createdAt,
      updatedAt: plugin.lastUpdatedAt || plugin.createdAt
    }

    // 缓存结果
    await cache.set(cacheKey, details, 300) // 5分钟缓存

    return details
  }

  // 通过ID获取插件详情
  async getPluginDetailsById(pluginId: string): Promise<PluginDetails> {
    // 尝试从缓存获取
    const cacheKey = `plugin:id:${pluginId}`
    const cached = await cache.get<PluginDetails>(cacheKey)
    if (cached) {
      return cached
    }

    const plugin = await prisma.plugin.findFirst({
      where: {
        id: pluginId,
        status: 'approved'
      },
      include: {
        developer: {
          select: {
            username: true,
            displayName: true,
            verified: true
          }
        },
        versions: {
          where: { status: 'approved' },
          select: {
            version: true,
            publishedAt: true,
            downloadCount: true,
            changelog: true
          },
          orderBy: { publishedAt: 'desc' }
        }
      }
    })

    if (!plugin) {
      throw new NotFoundError('Plugin not found')
    }

    // 计算统计数据
    const now = new Date()
    const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
    const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000)

    const [weeklyDownloads, monthlyDownloads] = await Promise.all([
      prisma.download.count({
        where: {
          pluginId: plugin.id,
          downloadedAt: { gte: weekAgo }
        }
      }),
      prisma.download.count({
        where: {
          pluginId: plugin.id,
          downloadedAt: { gte: monthAgo }
        }
      })
    ])

    const details: PluginDetails = {
      id: plugin.id,
      name: plugin.name,
      displayName: plugin.displayName,
      description: plugin.description || undefined,
      category: plugin.category,
      developer: {
        username: plugin.developer.username,
        displayName: plugin.developer.displayName || undefined,
        verified: plugin.developer.verified
      },
      repositoryUrl: plugin.repositoryUrl || undefined,
      homepageUrl: plugin.homepageUrl || undefined,
      documentationUrl: plugin.documentationUrl || undefined,
      license: plugin.license || undefined,
      keywords: plugin.keywords,
      latestVersion: plugin.lastVersion || undefined,
      totalDownloads: Number(plugin.totalDownloads),
      rating: {
        average: Number(plugin.ratingAverage),
        count: plugin.ratingCount
      },
      featured: plugin.featured,
      verified: plugin.verified,
      tags: plugin.tags,
      versions: plugin.versions.map(v => ({
        version: v.version,
        publishedAt: v.publishedAt!,
        downloadCount: Number(v.downloadCount),
        changelog: v.changelog || undefined
      })),
      stats: {
        weeklyDownloads,
        monthlyDownloads
      },
      createdAt: plugin.createdAt,
      updatedAt: plugin.lastUpdatedAt || plugin.createdAt
    }

    // 缓存结果
    await cache.set(cacheKey, details, 300) // 5分钟缓存

    return details
  }

  // 清除插件缓存
  private async clearPluginCache(pluginName: string): Promise<void> {
    await cache.del(`plugin:${pluginName}`)
  }

  // 下载插件
  async downloadPlugin(pluginName: string, version: string): Promise<{
    fileStream: ReadableStream
    fileSize: number
    filename: string
  }> {
    // 查找插件版本
    const pluginVersion = await prisma.pluginVersion.findFirst({
      where: {
        plugin: {
          name: pluginName,
          status: 'approved'
        },
        version,
        status: 'approved'
      },
      include: {
        plugin: {
          select: {
            name: true,
            displayName: true
          }
        }
      }
    })

    if (!pluginVersion) {
      throw new NotFoundError('Plugin version not found')
    }

    // 检查文件是否存在
    const fs = await import('fs')
    if (!fs.existsSync(pluginVersion.filePath)) {
      throw new NotFoundError('Plugin file not found')
    }

    // 增加下载计数
    await Promise.all([
      // 更新版本下载计数
      prisma.pluginVersion.update({
        where: { id: pluginVersion.id },
        data: { downloadCount: { increment: 1 } }
      }),
      // 更新插件总下载计数
      prisma.plugin.update({
        where: { id: pluginVersion.pluginId },
        data: { totalDownloads: { increment: 1 } }
      }),
      // 记录下载日志
      prisma.download.create({
        data: {
          pluginId: pluginVersion.pluginId,
          versionId: pluginVersion.id,
          downloadedAt: new Date()
        }
      })
    ])

    // 创建文件流
    const fileStream = fs.createReadStream(pluginVersion.filePath)

    // 转换为Web ReadableStream
    const webStream = new ReadableStream({
      start(controller) {
        fileStream.on('data', (chunk: any) => {
          const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
          controller.enqueue(new Uint8Array(buffer))
        })
        fileStream.on('end', () => {
          controller.close()
        })
        fileStream.on('error', (error) => {
          controller.error(error)
        })
      }
    })

    // 清除相关缓存
    await this.clearPluginCache(pluginName)

    return {
      fileStream: webStream,
      fileSize: Number(pluginVersion.fileSize),
      filename: `${pluginName}-${version}.zip`
    }
  }

  // 获取插件版本列表
  async getPluginVersions(pluginName: string): Promise<{
    versions: {
      version: string
      publishedAt: Date
      downloadCount: number
      changelog?: string
      status: string
    }[]
  }> {
    const plugin = await prisma.plugin.findUnique({
      where: {
        name: pluginName,
        status: 'approved'
      },
      include: {
        versions: {
          where: { status: 'approved' },
          select: {
            version: true,
            publishedAt: true,
            downloadCount: true,
            changelog: true,
            status: true
          },
          orderBy: { publishedAt: 'desc' }
        }
      }
    })

    if (!plugin) {
      throw new NotFoundError('Plugin not found')
    }

    const versions = plugin.versions.map(v => ({
      version: v.version,
      publishedAt: v.publishedAt!,
      downloadCount: Number(v.downloadCount),
      changelog: v.changelog || undefined,
      status: v.status
    }))

    return { versions }
  }

  // 获取插件manifest
  async getPluginManifest(pluginName: string, version: string): Promise<any> {
    const pluginVersion = await prisma.pluginVersion.findFirst({
      where: {
        plugin: {
          name: pluginName,
          status: 'approved'
        },
        version,
        status: 'approved'
      },
      select: {
        manifest: true
      }
    })

    if (!pluginVersion) {
      throw new NotFoundError('Plugin version not found')
    }

    return pluginVersion.manifest
  }

  // 获取开发者的单个插件详情
  async getDeveloperPlugin(developerId: string, pluginId: string): Promise<any> {
    const plugin = await prisma.plugin.findFirst({
      where: {
        id: pluginId,
        developerId
      },
      include: {
        developer: {
          select: {
            username: true,
            displayName: true,
            verified: true
          }
        },
        versions: {
          select: {
            id: true,
            version: true,
            status: true,
            downloadCount: true,
            publishedAt: true,
            createdAt: true
          },
          orderBy: { createdAt: 'desc' }
        }
      }
    })

    if (!plugin) {
      throw new NotFoundError('Plugin not found')
    }

    return {
      ...plugin,
      totalDownloads: Number(plugin.totalDownloads),
      ratingAverage: Number(plugin.ratingAverage),
      ratingCount: plugin.ratingCount,
      versions: plugin.versions.map(v => ({
        ...v,
        downloadCount: Number(v.downloadCount)
      }))
    }
  }

  // 更新插件信息
  async updatePlugin(developerId: string, pluginId: string, data: Partial<CreatePluginData>): Promise<any> {
    // 验证插件所有权
    const existingPlugin = await prisma.plugin.findFirst({
      where: {
        id: pluginId,
        developerId
      }
    })

    if (!existingPlugin) {
      throw new NotFoundError('Plugin not found')
    }

    // 如果要更新插件名称，检查是否冲突
    if (data.name && data.name !== existingPlugin.name) {
      const nameConflict = await prisma.plugin.findUnique({
        where: { name: data.name }
      })

      if (nameConflict) {
        throw new ConflictError('Plugin name already exists')
      }
    }

    // 如果要更新分类，验证分类是否存在
    if (data.category) {
      const category = await prisma.category.findUnique({
        where: { name: data.category }
      })

      if (!category) {
        throw new ValidationError('Invalid category')
      }
    }

    // 更新插件
    const updatedPlugin = await prisma.plugin.update({
      where: { id: pluginId },
      data: {
        ...(data.displayName && { displayName: data.displayName }),
        ...(data.description !== undefined && { description: data.description }),
        ...(data.category && { category: data.category }),
        ...(data.repositoryUrl !== undefined && { repositoryUrl: data.repositoryUrl }),
        ...(data.homepageUrl !== undefined && { homepageUrl: data.homepageUrl }),
        ...(data.documentationUrl !== undefined && { documentationUrl: data.documentationUrl }),
        ...(data.license !== undefined && { license: data.license }),
        ...(data.keywords && { keywords: data.keywords }),
        ...(data.tags && { tags: data.tags })
      },
      include: {
        developer: {
          select: {
            username: true,
            displayName: true,
            verified: true
          }
        }
      }
    })

    // 清除相关缓存
    await this.clearPluginCache(existingPlugin.name)
    await this.clearPluginListCache()

    return {
      ...updatedPlugin,
      totalDownloads: Number(updatedPlugin.totalDownloads),
      ratingAverage: Number(updatedPlugin.ratingAverage),
      ratingCount: updatedPlugin.ratingCount
    }
  }

  // 删除插件
  async deletePlugin(developerId: string, pluginId: string): Promise<void> {
    // 验证插件所有权
    const plugin = await prisma.plugin.findFirst({
      where: {
        id: pluginId,
        developerId
      }
    })

    if (!plugin) {
      throw new NotFoundError('Plugin not found')
    }

    // 检查是否有已发布的版本
    const publishedVersions = await prisma.pluginVersion.count({
      where: {
        pluginId,
        status: 'approved'
      }
    })

    if (publishedVersions > 0) {
      throw new ValidationError('Cannot delete plugin with published versions. Please contact support.')
    }

    // 删除插件及其相关数据
    await prisma.$transaction(async (tx) => {
      // 获取所有版本ID用于删除安全扫描记录
      const versions = await tx.pluginVersion.findMany({
        where: { pluginId },
        select: { id: true }
      })
      const versionIds = versions.map(v => v.id)

      // 删除安全扫描记录
      if (versionIds.length > 0) {
        await tx.securityScan.deleteMany({
          where: { versionId: { in: versionIds } }
        })
      }

      // 删除插件版本
      await tx.pluginVersion.deleteMany({
        where: { pluginId }
      })

      // 删除下载记录
      await tx.download.deleteMany({
        where: { pluginId }
      })

      // 删除评论
      await tx.review.deleteMany({
        where: { pluginId }
      })

      // 删除插件标签关联
      await tx.pluginTag.deleteMany({
        where: { pluginId }
      })

      // 最后删除插件
      await tx.plugin.delete({
        where: { id: pluginId }
      })
    })

    // 清除相关缓存
    await this.clearPluginCache(plugin.name)
    await this.clearPluginListCache()
  }

  // 获取开发者的插件列表
  async getDeveloperPlugins(developerId: string, options: {
    page?: number
    limit?: number
    status?: string
    search?: string
  }): Promise<{
    plugins: any[]
    pagination: {
      page: number
      limit: number
      total: number
      totalPages: number
    }
  }> {
    const page = options.page || 1
    const limit = Math.min(options.limit || 20, 100)
    const offset = (page - 1) * limit

    // 构建查询条件
    const where: any = {
      developerId
    }

    if (options.status && options.status !== 'all') {
      where.status = options.status
    }

    if (options.search) {
      where.OR = [
        { displayName: { contains: options.search, mode: 'insensitive' } },
        { description: { contains: options.search, mode: 'insensitive' } },
        { keywords: { has: options.search } }
      ]
    }

    // 查询插件
    const [plugins, total] = await Promise.all([
      prisma.plugin.findMany({
        where,
        include: {
          versions: {
            select: {
              version: true,
              status: true,
              publishedAt: true,
              downloadCount: true
            },
            orderBy: { publishedAt: 'desc' },
            take: 1
          },
          _count: {
            select: {
              versions: true
            }
          }
        },
        orderBy: { updatedAt: 'desc' },
        skip: offset,
        take: limit
      }),
      prisma.plugin.count({ where })
    ])

    // 转换数据格式
    const pluginList = plugins.map(plugin => ({
      id: plugin.id,
      name: plugin.name,
      displayName: plugin.displayName,
      description: plugin.description || undefined,
      category: plugin.category,
      status: plugin.status,
      featured: plugin.featured,
      verified: plugin.verified,
      totalDownloads: Number(plugin.totalDownloads),
      rating: {
        average: Number(plugin.ratingAverage),
        count: plugin.ratingCount
      },
      latestVersion: plugin.versions[0]?.version || null,
      versionCount: plugin._count.versions,
      tags: plugin.tags,
      createdAt: plugin.createdAt,
      updatedAt: plugin.updatedAt
    }))

    return {
      plugins: pluginList,
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit)
      }
    }
  }

  // 清除插件列表缓存
  private async clearPluginListCache(): Promise<void> {
    await cache.delPattern('plugin-list:*')
  }
}
